package com.one.blocks.rbac.datascope;

import com.one.blocks.mvc.domain.SearchParam;
import com.one.blocks.mvc.util.ScopeWebRequestHelper;
import com.one.blocks.rbac.domain.SysRole;
import com.one.blocks.rbac.enums.DataScopeEnum;
import com.one.blocks.rbac.manager.SysRoleManager;
import com.one.blocks.rbac.util.SubjectHelper;
import lombok.extern.slf4j.Slf4j;
import org.apache.commons.collections4.CollectionUtils;
import org.aspectj.lang.ProceedingJoinPoint;
import org.aspectj.lang.annotation.Around;
import org.aspectj.lang.annotation.Aspect;
import org.aspectj.lang.annotation.Pointcut;

import java.util.ArrayList;
import java.util.List;
import java.util.Map;
import java.util.stream.Collectors;

import static com.one.blocks.rbac.constant.RbacConstant.ScopeRequest.ROLES_OF_USER_ID;

/**
 * -- 本人数据
 * select * from t where create_id = ?
 * -- 自定义
 * select * from t where org_id in (select org_id from sys_role_org where role_id in (?))
 * -- 本部门
 * select * from t where org_id in (select org_id from sys_user_org b where b.user_id = ?)
 * -- 本部门及以下
 * select * from t where org_id in (select b.id from sys_org b inner join (select full_code from sys_org so inner join sys_user_org suo on so.id = suo.org_id and user_id = ?) c on b.full_code like concat(c.full_code, '%'))
 * @author <a href="mailto:idler41@163.con">linfuxin</a> created on 2023-12-29 15:06:51
 */
@Aspect
@Slf4j
public class DataScopeAspect {

    /**
     * 数据权限过滤关键字
     */
    public static final String DATA_SCOPE = "dataScope";

    private final SysRoleManager sysRoleManager;

    public DataScopeAspect(SysRoleManager sysRoleManager) {
        this.sysRoleManager = sysRoleManager;
    }

    @Pointcut(value = "@annotation(com.one.blocks.rbac.datascope.DataScope)")
    public void logPointCut() {
    }

    @Around("logPointCut() && @annotation(logInfo)")
    public Object around(ProceedingJoinPoint joinPoint, DataScope dataScope) throws Throwable {
        // 查询权限关联的角色
        Integer userId = SubjectHelper.getSubjectId();
        if (userId == null) {
            throw new IllegalStateException("userId is null");
        }
        List<SysRole> sysRoleList = ScopeWebRequestHelper.get(ROLES_OF_USER_ID + userId, () -> sysRoleManager.findByUserId(userId));
        try {
            Object params = joinPoint.getArgs()[0];
            if (!(params instanceof SearchParam)) {
                throw new IllegalArgumentException("参数不是SearchParam子类!classType=" + params.getClass());
            }
            // 管理员查询所有数据，不作额外处理
            if (CollectionUtils.isNotEmpty(sysRoleList) && sysRoleList.stream().noneMatch(i -> DataScopeEnum.ALL.match(i.getDataScope()))) {
                processDataScope(dataScope, (SearchParam) params, sysRoleList);
            }
            return joinPoint.proceed();
        } finally {

        }
    }

    protected void processDataScope(DataScope dataScope, SearchParam params, List<SysRole> sysRoleList) {
        // 分组
        Map<Integer, List<SysRole>> sysRoleMap = sysRoleList.stream().collect(Collectors.groupingBy(SysRole::getDataScope));

        List<String> subSqlList = new ArrayList<>(sysRoleMap.keySet().size());
        for (Integer scopeType : sysRoleMap.keySet()) {
            String subSql = null;
            if (DataScopeEnum.CUSTOM.match(scopeType)) {
                subSql = "";
            } else if (DataScopeEnum.CURRENT_NODE.match(scopeType)) {
                subSql = "";
            } else if (DataScopeEnum.NODE_AND_CHILD.match(scopeType)) {
                subSql = "";
            } else {
                // 未知
            }
            subSqlList.add(subSql);
        }
        String sql = String.join(" OR ", subSqlList);
        params.getParams().put(DATA_SCOPE, "(" + sql + ")");
    }
}
